home *** CD-ROM | disk | FTP | other *** search
/ New Star Software Collection / NSS_Collection.iso / 3-004 ms visual basic pro 30 / 4.imz / 4.IMA / CIRC3.C_ / CIRC3.bin
Text File  |  1993-04-28  |  24KB  |  845 lines

  1. //---------------------------------------------------------------------------
  2. //        Copyright (C) 1991-93, Microsoft Corporation
  3. //
  4. // You have a royalty-free right to use, modify, reproduce and distribute
  5. // the Sample Custom Control Files (and/or any modified version) in any way
  6. // you find useful, provided that you agree that Microsoft has no warranty,
  7. // obligation or liability for any Custom Control File.
  8. //---------------------------------------------------------------------------
  9. // Circ3.c
  10. //---------------------------------------------------------------------------
  11. // Contains control procedure for CIRC3 control
  12. //---------------------------------------------------------------------------
  13.  
  14. #include <windows.h>
  15. #include <vbapi.h>
  16. #include <string.h>
  17. #include "circ3.h"       // Declares Vb3.0 compatable model information
  18. #include "circ3vb2.h"    // Declares Vb2.0 compatable model information
  19. #include "circ3vb1.h"    // Declares Vb1.0 compatable model information
  20.  
  21.  
  22. //---------------------------------------------------------------------------
  23. // Local Prototypes
  24. //---------------------------------------------------------------------------
  25. VOID NEAR PaintCircle(HCTL hctl, HWND hwnd, HDC hdc);
  26. VOID NEAR RecalcArea(HCTL hctl, HWND hwnd);
  27. VOID NEAR FlashCircle(HCTL hctl, HDC hdc);
  28. BOOL NEAR InCircle(HCTL hctl, SHORT xcoord, SHORT ycoord);
  29. VOID NEAR FireClickIn(HCTL hctl, HWND hwnd, SHORT x, SHORT y);
  30. VOID NEAR FireClickOut(HCTL hctl);
  31. HWND NEAR HwndInitFlashPopup(VOID);
  32. VOID NEAR DisplayHelpTopic(CHAR chKeylist, LPSTR lpszKeyword);
  33. BOOL _export FAR PASCAL FlashDlgProc(HWND hDlg, USHORT msg, USHORT wp, LONG lp);
  34.  
  35.  
  36. //---------------------------------------------------------------------------
  37. // Global Variables
  38. //---------------------------------------------------------------------------
  39. HANDLE hmodDLL;
  40. WORD   cVbxUsers = 0;
  41. BOOL   fDevTimeInited = FALSE;
  42.  
  43.  
  44. //---------------------------------------------------------------------------
  45. // Global Variables for FlashColor dialog
  46. //---------------------------------------------------------------------------
  47. BOOL   fDlgInUse = FALSE;
  48. HCTL   hctlDialog;
  49. USHORT ipropDialog;
  50. LONG   colorOldDialog;
  51.  
  52.  
  53. //---------------------------------------------------------------------------
  54. // Circle Control Procedure
  55. //---------------------------------------------------------------------------
  56. LONG FAR PASCAL _export CircleCtlProc
  57. (
  58.     HCTL   hctl,
  59.     HWND   hwnd,
  60.     USHORT msg,
  61.     USHORT wp,
  62.     LONG   lp
  63. )
  64. {
  65.     switch (msg)
  66.     {
  67.     case VBM_DATA_AVAILABLE:
  68.         {
  69.         ERR    err;
  70.         HSZ hszFieldName;
  71.         LONG lData;
  72.         LPDATAACCESS lpda;
  73.  
  74.         lpda = (LPDATAACCESS)lp;
  75.  
  76.         switch (lpda->sAction) {
  77.             case DATA_CLOSE:
  78.             case DATA_DELETE:
  79.             case DATA_UNLOAD:
  80.                 VBSetControlFlags(hctl, CTLFLG_DATACHANGED, 0L);
  81.                 return 0;
  82.             default:
  83.                 break;
  84.         }
  85.  
  86.         err = (ERR)VBGetControlProperty(hctl, IPROP_CIRCLE_DATAFIELD, &hszFieldName);
  87.         if (err)
  88.             return err;
  89.  
  90.         if (!hszFieldName || *VBDerefHsz(hszFieldName) == 0) {
  91.             if (hszFieldName)
  92.                 VBDestroyHsz(hszFieldName);    
  93.             return 0;
  94.         }
  95.  
  96.         lpda->hszDataField = hszFieldName;
  97.         lpda->sAction = DATA_FIELDVALUE;
  98.         lpda->usDataType = DT_HSZ;
  99.         lpda->lData = NULL;
  100.  
  101.         err = (ERR)VBSendControlMsg(lpda->hctlData, VBM_DATA_GET, 0, (LONG)lpda);
  102.         if (err || !lpda->lData) {
  103.             VBDestroyHsz(hszFieldName);
  104.             return err;
  105.         }
  106.  
  107.         lData = (LONG)VBLockHsz((HSZ)lpda->lData);
  108.         
  109.         VBSetControlFlags(hctl, CTLFLG_DATACHANGED, 0L);
  110.         VBSetControlFlags(hctl, CTLFLG_BOUNDDATASET, CTLFLG_BOUNDDATASET);
  111.         err = VBSetControlProperty(lpda->hctlBound, IPROP_CIRCLE_CAPTION, lData);
  112.         VBSetControlFlags(hctl, CTLFLG_BOUNDDATASET, 0L);
  113.  
  114.         VBUnlockHsz((HSZ)lpda->lData);
  115.         VBDestroyHsz(hszFieldName);
  116.         VBDestroyHsz((HSZ)lpda->lData);
  117.         return err;
  118.         }
  119.  
  120.     case VBM_DATA_REQUEST:
  121.         {
  122.         ERR    err;
  123.         HSZ hszCaption;
  124.         HSZ hszFieldName;
  125.         LPDATAACCESS lpda;
  126.  
  127.         lpda = (LPDATAACCESS)lp;
  128.  
  129.         if (!(VBSetControlFlags(hctl, 0L, 0L) & CTLFLG_DATACHANGED))
  130.             return 0;
  131.             
  132.         err = (ERR)VBGetControlProperty(hctl, IPROP_CIRCLE_DATAFIELD, &hszFieldName);
  133.         if (err)
  134.             return err;
  135.  
  136.         if (!hszFieldName || *VBDerefHsz(hszFieldName) == 0) {
  137.             if (hszFieldName)
  138.                 VBDestroyHsz(hszFieldName);    
  139.             return 0;
  140.         }
  141.  
  142.         err = (ERR)VBGetControlProperty(hctl, IPROP_CIRCLE_CAPTION, &hszCaption);
  143.         if (err) {
  144.             VBDestroyHsz(hszFieldName);    
  145.             return err;
  146.         }
  147.  
  148.         lpda->hszDataField = hszFieldName;
  149.         lpda->sAction = DATA_FIELDVALUE;
  150.         lpda->usDataType = DT_HSZ;
  151.         lpda->lData = hszCaption;
  152.  
  153.         err = (ERR)VBSendControlMsg(lpda->hctlData, VBM_DATA_SET, 0, (LONG)lpda);
  154.         
  155.         if (!err)
  156.             VBSetControlFlags(hctl, CTLFLG_DATACHANGED, 0L);
  157.  
  158.         VBDestroyHsz(hszFieldName);
  159.         VBDestroyHsz(hszCaption);
  160.         return err;
  161.         }
  162.  
  163.     case WM_NCCREATE:
  164.         {
  165.         LPCIRC lpcirc = (LPCIRC)VBDerefControl(hctl);
  166.  
  167.         lpcirc->CircleShape = SHAPE_CIRCLE;
  168.         lpcirc->FlashColor = 128L;
  169.         VBSetControlProperty(hctl, IPROP_CIRCLE_BACKCOLOR, 255L);
  170.         // *** lpcirc may now be invalid due to call to VB API ***
  171.         break;
  172.         }
  173.  
  174.         case WM_LBUTTONDOWN:
  175.         case WM_LBUTTONDBLCLK:
  176.         if (InCircle(hctl, (SHORT)lp, (SHORT)HIWORD(lp)))
  177.         {
  178.         HDC hdc = GetDC(hwnd);
  179.  
  180.         FlashCircle(hctl, hdc);
  181.         ReleaseDC(hwnd, hdc);
  182.         FireClickIn(hctl, hwnd, (SHORT)lp, (SHORT)HIWORD(lp));
  183.         }
  184.         else
  185.         FireClickOut(hctl);
  186.             break;
  187.  
  188.         case WM_LBUTTONUP:
  189.         if (InCircle(hctl, (SHORT)lp, (SHORT)HIWORD(lp)))
  190.         {
  191.         HDC hdc = GetDC(hwnd);
  192.  
  193.         PaintCircle(hctl, hwnd, hdc);
  194.         ReleaseDC(hwnd, hdc);
  195.         }
  196.             break;
  197.  
  198.         case WM_SETFONT:
  199.         LpcircDEREF(hctl)->hfont = (HFONT)wp;
  200.             return 0;
  201.  
  202.         case WM_GETFONT:
  203.         return LpcircDEREF(hctl)->hfont;
  204.  
  205.         case WM_SETTEXT:
  206.             {
  207.         HSZ    hsz;
  208.         LPCIRC lpcirc = LpcircDEREF(hctl);
  209.  
  210.         if (lpcirc->hszCaption)
  211.         {
  212.         VBDestroyHsz(lpcirc->hszCaption);
  213.         // *** lpcirc may now be invalid due to call to VB API ***
  214.         }
  215.         hsz = VBCreateHsz((_segment)hctl, (LPSTR)lp);
  216.         // *** lpcirc may now be invalid due to call to VB API ***
  217.         LpcircDEREF(hctl)->hszCaption = hsz;
  218.         InvalidateRect(hwnd, NULL, TRUE);
  219.         return 0L;
  220.             }
  221.  
  222.         case WM_GETTEXT:
  223.             {
  224.         LPSTR  lpstr;
  225.         USHORT cch;
  226.         LPCIRC lpcirc = LpcircDEREF(hctl);
  227.  
  228.         if (lpcirc->hszCaption == NULL)
  229.         {
  230.         *(LPSTR)lp = 0L;
  231.         wp = 1;
  232.         }
  233.         else
  234.         {
  235.         lpstr = VBDerefHsz(lpcirc->hszCaption);
  236.         cch = (USHORT)(lstrlen(lpstr) + 1);
  237.         if (wp > cch)
  238.             wp = cch;
  239.         _fstrncpy((LPSTR)lp, lpstr, wp);
  240.         ((LPSTR)lp)[wp - 1] = '\0';
  241.         }
  242.             }
  243.         return (LONG)(wp - 1);
  244.  
  245.     case WM_GETTEXTLENGTH:
  246.         {
  247.         LPCIRC lpcirc = LpcircDEREF(hctl);
  248.  
  249.         if (lpcirc->hszCaption == NULL)
  250.                 return 0L;
  251.             else
  252.         return lstrlen(VBDerefHsz(lpcirc->hszCaption));
  253.         }
  254.  
  255.  
  256.         case WM_PAINT:
  257.             if (wp)
  258.         PaintCircle(hctl, hwnd, (HDC)wp);
  259.         else
  260.         {
  261.                 PAINTSTRUCT ps;
  262.  
  263.         BeginPaint(hwnd, &ps);
  264.         PaintCircle(hctl, hwnd, ps.hdc);
  265.         EndPaint(hwnd, &ps);
  266.         }
  267.             break;
  268.  
  269.         case WM_SIZE:
  270.         RecalcArea(hctl, hwnd);
  271.             break;
  272.  
  273.         case VBM_SETPROPERTY:
  274.         switch (wp)
  275.         {
  276.                 case IPROP_CIRCLE_CIRCLESHAPE:
  277.             LpcircDEREF(hctl)->CircleShape = (ENUM)lp;
  278.             RecalcArea(hctl, hwnd);
  279.             InvalidateRect(hwnd, NULL, TRUE);
  280.             return 0L;
  281.  
  282.                 case IPROP_CIRCLE_CAPTION:
  283.                     VBSetControlFlags(hctl, CTLFLG_DATACHANGED, CTLFLG_DATACHANGED);
  284.         }
  285.             break;
  286.  
  287.     case VBM_HELP:
  288.         switch (LOBYTE(wp))
  289.         {
  290.         case VBHELP_PROP:
  291.             // High byte identifies which property.
  292.             // Keyword is: "<property>"
  293.             switch (HIBYTE(wp))
  294.             {
  295.             case IPROP_CIRCLE_CIRCLESHAPE:
  296.                 DisplayHelpTopic('P', "CircleShape");
  297.                 return 0L;
  298.  
  299.             case IPROP_CIRCLE_FLASHCOLOR:
  300.                 DisplayHelpTopic('P', "FlashColor");
  301.                 return 0L;
  302.             }
  303.             break;
  304.  
  305.         case VBHELP_EVT:
  306.             // High byte identifies which event
  307.             // Keyword is: "<event>"
  308.             switch (HIBYTE(wp))
  309.             {
  310.             case IEVENT_CIRCLE_CLICKIN:
  311.                 DisplayHelpTopic('V', "ClickIn");
  312.                 return 0L;
  313.  
  314.             case IEVENT_CIRCLE_CLICKOUT:
  315.                 DisplayHelpTopic('V', "ClickOut");
  316.                 return 0L;
  317.             }
  318.             break;
  319.  
  320.         case VBHELP_CTL:
  321.             // High byte is unused.
  322.             // Keyword is: "<classname>"
  323.             DisplayHelpTopic('C', "CIRC3");
  324.             return 0L;
  325.         }
  326.         break;
  327.  
  328.         case VBM_INITPROPPOPUP:
  329.         switch (wp)
  330.         {
  331.         // Un-commenting the following line will enable our custom
  332.         // popup instead of the color palette, when setting the
  333.         // backcolor:
  334.         // case IPROP_CIRCLE_BACKCOLOR:
  335.         case IPROP_CIRCLE_FLASHCOLOR:
  336.             {
  337.             if (fDlgInUse)
  338.               // Our dialog is already in use, so return NULL here
  339.               // to avoid bringing up a 2nd instance of the dialog.
  340.               // We could get around this restriction by storing
  341.               // hctlDialog, ipropDialog, and colorOldDialog as
  342.               // window words of hwndPopup.
  343.               // NOTE: In this specific case, because FlashColor
  344.               // is DT_COLOR, we could also just "break;" to go
  345.               // through default processing which would bring up
  346.               // the default color palette.
  347.               return NULL;
  348.  
  349.             // Tell the hwndPopup which control and iprop we want
  350.             // the dialog to change
  351.             fDlgInUse    = TRUE;
  352.             hctlDialog    = hctl;
  353.             ipropDialog = wp;
  354.  
  355.             return HwndInitFlashPopup();
  356.             }
  357.                 }
  358.             break;
  359.     }
  360.  
  361.     return VBDefControlProc(hctl, hwnd, msg, wp, lp);
  362. }
  363.  
  364.  
  365. //---------------------------------------------------------------------------
  366. // Handle painting by drawing circle into the given hdc.
  367. //---------------------------------------------------------------------------
  368. VOID NEAR PaintCircle
  369. (
  370.     HCTL hctl,
  371.     HWND hwnd,
  372.     HDC  hdc
  373. )
  374. {
  375.     HBRUSH hbr;
  376.     HBRUSH hbrOld = NULL;
  377.     LPSTR  lpstr;
  378.     LPCIRC lpcirc = LpcircDEREF(hctl);
  379.     LPRECT lprect = &lpcirc->rectDrawInto;
  380.     HFONT  hfontOld = NULL;
  381.  
  382.     hbr = (HBRUSH)SendMessage(GetParent(hwnd), WM_CTLCOLOR,
  383.                   hdc, MAKELONG(hwnd, 0));
  384.     if (hbr)
  385.     hbrOld = SelectObject(hdc, hbr);
  386.     Ellipse(hdc, lprect->left, lprect->top, lprect->right, lprect->bottom);
  387.  
  388.     if (lpcirc->hfont)
  389.       hfontOld = SelectObject(hdc, lpcirc->hfont);
  390.     lpstr = VBDerefHsz(lpcirc->hszCaption);
  391.     DrawText(hdc, lpstr, -1, lprect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
  392.  
  393.     if (hbrOld)
  394.     SelectObject(hdc, hbrOld);
  395.     if (hfontOld)
  396.     SelectObject(hdc, hfontOld);
  397. }
  398.  
  399.  
  400. //---------------------------------------------------------------------------
  401. // Paint the circle in the FlashColor.
  402. //---------------------------------------------------------------------------
  403. VOID NEAR FlashCircle
  404. (
  405.     HCTL hctl,
  406.     HDC  hdc
  407. )
  408. {
  409.     HBRUSH hbr;
  410.     HBRUSH hbrOld = NULL;
  411.     LPCIRC lpcirc = LpcircDEREF(hctl);
  412.     LPRECT lprect = &lpcirc->rectDrawInto;
  413.  
  414.     hbr = CreateSolidBrush(RGBCOLOR(lpcirc->FlashColor));
  415.     if (hbr)
  416.     hbrOld = SelectObject(hdc, hbr);
  417.     Ellipse(hdc, lprect->left, lprect->top, lprect->right, lprect->bottom);
  418.     if (hbr)
  419.     {
  420.     SelectObject(hdc, hbrOld);
  421.     DeleteObject(hbr);
  422.     }
  423. }
  424.  
  425.  
  426. //---------------------------------------------------------------------------
  427. // Use the hwnd's client size to determine the bounding rectangle for the
  428. // circle.  If CircleShape is TRUE, then we need to calculate a square
  429. // centered in lprect.
  430. //---------------------------------------------------------------------------
  431. VOID NEAR RecalcArea
  432. (
  433.     HCTL hctl,
  434.     HWND hwnd
  435. )
  436. {
  437.     LPCIRC lpcirc = LpcircDEREF(hctl);
  438.     LPRECT lprect = &lpcirc->rectDrawInto;
  439.  
  440.     GetClientRect(hwnd, lprect);
  441.     if (lpcirc->CircleShape == SHAPE_OVAL)
  442.         return;
  443.     if (lprect->right > lprect->bottom)
  444.     {
  445.     lprect->left = (lprect->right - lprect->bottom) / 2;
  446.     lprect->right = lprect->left + lprect->bottom;
  447.     }
  448.     else if (lprect->bottom > lprect->right)
  449.     {
  450.     lprect->top = (lprect->bottom - lprect->right) / 2;
  451.     lprect->bottom = lprect->top + lprect->right;
  452.     }
  453. }
  454.  
  455.  
  456. //---------------------------------------------------------------------------
  457. // Return TRUE if the given coordinates are inside of the circle.
  458. //---------------------------------------------------------------------------
  459. BOOL NEAR InCircle
  460. (
  461.     HCTL  hctl,
  462.     SHORT xcoord,
  463.     SHORT ycoord
  464. )
  465. {
  466.     double a, b;
  467.     double x, y;
  468.     LPRECT lprect = &LpcircDEREF(hctl)->rectDrawInto;
  469.  
  470.     a = (lprect->right - lprect->left) / 2;
  471.     b = (lprect->bottom - lprect->top) / 2;
  472.     x = xcoord - (lprect->left + lprect->right) / 2;
  473.     y = ycoord - (lprect->top + lprect->bottom) / 2;
  474.     return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
  475. }
  476.  
  477.  
  478. //---------------------------------------------------------------------------
  479. // TYPEDEF for parameters to the ClickIn event.
  480. //---------------------------------------------------------------------------
  481. typedef struct tagCLICKINPARMS
  482.     {
  483.     HLSTR      ClickString;
  484.     float far *Y;
  485.     float far *X;
  486.     LPVOID     Index;
  487.     } CLICKINPARMS;
  488.  
  489.  
  490. //---------------------------------------------------------------------------
  491. // Fire the ClickIn event, passing the x,y coords of the click.  Also pass
  492. // the current caption of the Circle control, to demonstrate passing strings
  493. // to event procedures.
  494. //---------------------------------------------------------------------------
  495. VOID NEAR FireClickIn
  496. (
  497.     HCTL  hctl,
  498.     HWND  hwnd,
  499.     SHORT x,
  500.     SHORT y
  501. )
  502. {
  503.     CLICKINPARMS params;
  504.     float     xTwips, yTwips;
  505.     USHORT     cbCaption, err;
  506.     char     strBuf[20];
  507.  
  508.     xTwips = (float)VBXPixelsToTwips(x);
  509.     yTwips = (float)VBYPixelsToTwips(y);
  510.     params.X = &xTwips;
  511.     params.Y = &yTwips;
  512.  
  513.     cbCaption = (USHORT)GetWindowText(hwnd, strBuf, 20);
  514.     params.ClickString = VBCreateHlstr(strBuf, cbCaption);
  515.     err = VBFireEvent(hctl, IEVENT_CIRCLE_CLICKIN, ¶ms);
  516.     VBDestroyHlstr(params.ClickString);
  517. }
  518.  
  519.  
  520. //---------------------------------------------------------------------------
  521. // Fire the ClickOut event.
  522. //---------------------------------------------------------------------------
  523. VOID NEAR FireClickOut
  524. (
  525.     HCTL hctl
  526. )
  527. {
  528.     VBFireEvent(hctl, IEVENT_CIRCLE_CLICKOUT, NULL);
  529. }
  530.  
  531.  
  532. //---------------------------------------------------------------------------
  533. // Use frame variables to "allocate" a MULTIKEYHELP structure to pass to
  534. // WinHelp().
  535. //---------------------------------------------------------------------------
  536. VOID NEAR DisplayHelpTopic
  537. (
  538.     CHAR  chKeylist,
  539.     LPSTR lpszKeyword
  540. )
  541. {
  542.     char  rgch[100];
  543.     MULTIKEYHELP FAR *lpmkh = rgch;
  544.  
  545.     lpmkh->mkSize = sizeof(MULTIKEYHELP) + lstrlen(lpszKeyword);
  546.     if (lpmkh->mkSize > sizeof(rgch))
  547.     return;
  548.  
  549.     lpmkh->mkKeylist = chKeylist;
  550.     lstrcpy((LPSTR)lpmkh->szKeyphrase, lpszKeyword);
  551.     WinHelp(GetActiveWindow(), "circ3.hlp", HELP_MULTIKEY, (DWORD)lpmkh);
  552. }
  553.  
  554.  
  555. //---------------------------------------------------------------------------
  556. // Create our property popup-window.  Since we want to put up a dialog, this
  557. // window never becomes visible.  Instead, when asked to become visible, it
  558. // will post a message to itself, remining it to put up our dialog.
  559. //
  560. // NOTE: May return NULL!
  561. //---------------------------------------------------------------------------
  562. HWND NEAR HwndInitFlashPopup
  563. (
  564.     VOID
  565. )
  566. {
  567.     return CreateWindow(CLASS_FLASHPOPUP, NULL, WS_POPUP,
  568.             0, 0, 0, 0, NULL, NULL,
  569.             hmodDLL, NULL);
  570. }
  571.  
  572.  
  573. //---------------------------------------------------------------------------
  574. // We asked to show ourself, remain invisible and post a CM_OPENFLASHDLG to
  575. // ourself.  When we receive this message, open the dialog box.
  576. //---------------------------------------------------------------------------
  577. LONG _export FAR PASCAL FlashPopupWndProc
  578. (
  579.     HWND   hwnd,
  580.     USHORT msg,
  581.     USHORT wp,
  582.     LONG   lp
  583. )
  584. {
  585.     extern HANDLE hmodDLL;
  586.  
  587.     switch (msg)
  588.     {
  589.     case WM_DESTROY:
  590.         fDlgInUse = FALSE;
  591.         break;
  592.  
  593.         case WM_SHOWWINDOW:
  594.         if (wp)
  595.         {
  596.         PostMessage(hwnd, CM_OPENFLASHDLG, 0, 0L);
  597.         return 0L;
  598.         }
  599.             break;
  600.  
  601.     case CM_OPENFLASHDLG:
  602.         VBDialogBoxParam(hmodDLL, "FlashDlg", (FARPROC)FlashDlgProc, 0L);
  603.         return 0L;
  604.     }
  605.  
  606.     return DefWindowProc(hwnd, msg, wp, lp);
  607. }
  608.  
  609.  
  610. //---------------------------------------------------------------------------
  611. // An array mapping option buttons to RGB colors.
  612. //---------------------------------------------------------------------------
  613. long mpidcolor[] = { 0xff, 0xff00, 0xff0000 };
  614.  
  615.  
  616. //---------------------------------------------------------------------------
  617. // The Dialog Procedure for the FlashColor property dialog.
  618. //---------------------------------------------------------------------------
  619. BOOL FAR PASCAL _export FlashDlgProc
  620. (
  621.     HWND   hDlg,
  622.     USHORT msg,
  623.     USHORT wp,
  624.     LONG   lp
  625. )
  626. {
  627.     switch (msg)
  628.     {
  629.     case WM_INITDIALOG:
  630.         {
  631.         RECT rect;
  632.         int  nx, ny;      // New x and y
  633.         int  width, height;
  634.         int  i;
  635.         LONG colorOld;
  636.  
  637.         // Position dialog so it looks nice:
  638.         GetWindowRect(hDlg, &rect);
  639.         width  = rect.right - rect.left;
  640.         height = rect.bottom - rect.top;
  641.         nx = (GetSystemMetrics(SM_CXSCREEN) - width)  / 2;
  642.         ny = (GetSystemMetrics(SM_CYSCREEN) - height) / 3;
  643.         MoveWindow(hDlg, nx, ny, width, height, FALSE);
  644.  
  645.         // Remember the old value of this property, so we can restore it
  646.         // on cancel:
  647.         if (VBGetControlProperty(hctlDialog, ipropDialog, &colorOld))
  648.           EndDialog(hDlg, FALSE);
  649.  
  650.         // If the current color matches one of the option button colors,
  651.         // then set that option button:
  652.         for (i=0; i<sizeof(mpidcolor); i++)
  653.         if (mpidcolor[i] == colorOld)
  654.             CheckRadioButton(hDlg, DI_REDOPT, DI_BLUEOPT, i+DI_REDOPT);
  655.  
  656.         // Save away colorOld so we can use it later
  657.         colorOldDialog = colorOld;
  658.  
  659.         return TRUE;
  660.         }
  661.  
  662.         case WM_COMMAND:
  663.         switch (wp)
  664.         {
  665.                 case IDOK:
  666.             EndDialog(hDlg, TRUE);
  667.                     return TRUE;
  668.  
  669.         case IDCANCEL:
  670.             {
  671.             // Restore the old value, since we're canceling:
  672.             VBSetControlProperty(hctlDialog, ipropDialog, colorOldDialog);
  673.  
  674.             EndDialog(hDlg, FALSE);
  675.             return TRUE;
  676.             }
  677.  
  678.                 case DI_REDOPT:
  679.                 case DI_GREENOPT:
  680.         case DI_BLUEOPT:
  681.             {
  682.             CheckRadioButton(hDlg, DI_REDOPT, DI_BLUEOPT, wp);
  683.  
  684.             VBSetControlProperty(hctlDialog, ipropDialog,
  685.                      mpidcolor[wp-DI_REDOPT]);
  686.             return TRUE;
  687.             }
  688.         }
  689.             break;
  690.     }
  691.     return FALSE;
  692. }
  693.  
  694.  
  695. //---------------------------------------------------------------------------
  696. // Register custom control. This routine is called by VB when the custom
  697. // control DLL is loaded for use.
  698. //---------------------------------------------------------------------------
  699. BOOL FAR PASCAL _export VBINITCC
  700. (
  701.     USHORT usVersion,
  702.     BOOL   fRuntime
  703. )
  704. {
  705.     // Count the number of hosts using this VBX.  A host can be vb.exe,
  706.     // any .exe compiled from vb which uses this custom control, or any
  707.     // other program which loads and uses VBX files.
  708.     ++cVbxUsers;
  709.  
  710.     // Register popup class if this is from the development environment.
  711.     if (!fRuntime && !fDevTimeInited)
  712.     {
  713.     WNDCLASS class;
  714.  
  715.     class.style        = 0;
  716.     class.lpfnWndProc   = (FARPROC)FlashPopupWndProc;
  717.     class.cbClsExtra    = 0;
  718.     class.cbWndExtra    = 0;
  719.     class.hInstance     = hmodDLL;
  720.     class.hIcon        = NULL;
  721.     class.hCursor        = NULL;
  722.         class.hbrBackground = NULL;
  723.     class.lpszMenuName  = NULL;
  724.     class.lpszClassName = CLASS_FLASHPOPUP;
  725.  
  726.     if (!RegisterClass(&class))
  727.         return FALSE;
  728.  
  729.     // We successfully initialized the stuff we need at dev time
  730.     fDevTimeInited = TRUE;
  731.     }
  732.  
  733.     // Register control(s)
  734.     if (usVersion <= VB100_VERSION)
  735.         return VBRegisterModel(hmodDLL, &modelCircle_Vb1);
  736.  
  737.     if (usVersion <= VB200_VERSION)
  738.         return VBRegisterModel(hmodDLL, &modelCircle_Vb2);
  739.     else
  740.         return VBRegisterModel(hmodDLL, &modelCircle);
  741. }
  742.  
  743.  
  744. //---------------------------------------------------------------------------
  745. // Unregister custom control.  This routine is called by VB when the custom
  746. // control DLL is being unloaded.
  747. //---------------------------------------------------------------------------
  748. VOID FAR PASCAL _export VBTERMCC
  749. (
  750.     VOID
  751. )
  752. {
  753.     --cVbxUsers;
  754.     if (cVbxUsers == 0 && fDevTimeInited)
  755.     {
  756.     // Free any resources created for Dev environment
  757.     UnregisterClass(CLASS_FLASHPOPUP, hmodDLL);
  758.     }
  759.     return;
  760. }
  761.  
  762.  
  763. //---------------------------------------------------------------------------
  764. // Provide custom control model information to host environment.
  765. //---------------------------------------------------------------------------
  766. LPMODELINFO FAR PASCAL _export VBGetModelInfo
  767. (
  768.     USHORT usVersion
  769. )
  770. {
  771.     if (usVersion <= VB100_VERSION)
  772.         return &modelinfoCircle_Vb1;
  773.  
  774.     if (usVersion <= VB200_VERSION)
  775.         return &modelinfoCircle_Vb2;
  776.     else
  777.         return &modelinfoCircle;
  778. }
  779.  
  780.  
  781. //---------------------------------------------------------------------------
  782. // Initialize library.    This routine is called when the first client loads
  783. // the DLL.
  784. //---------------------------------------------------------------------------
  785. int FAR PASCAL LibMain
  786. (
  787.     HANDLE hModule,
  788.     WORD   wDataSeg,
  789.     WORD   cbHeapSize,
  790.     LPSTR  lpszCmdLine
  791. )
  792. {
  793.     // Avoid warnings on unused (but required) formal parameters
  794.     wDataSeg    = wDataSeg;
  795.     cbHeapSize    = cbHeapSize;
  796.     lpszCmdLine = lpszCmdLine;
  797.  
  798.     hmodDLL = hModule;
  799.  
  800.     return 1;
  801. }
  802.  
  803.  
  804. //---------------------------------------------------------------------------
  805. // WEP
  806. //---------------------------------------------------------------------------
  807. // C7 and QCWIN provide default a WEP:
  808. //---------------------------------------------------------------------------
  809. #if (_MSC_VER < 610)
  810.  
  811. int FAR PASCAL WEP(int fSystemExit);
  812.  
  813. //---------------------------------------------------------------------------
  814. // For Windows 3.0 it is recommended that the WEP function reside in a
  815. // FIXED code segment and be exported as RESIDENTNAME.  This is
  816. // accomplished using the alloc_text pragma below and the related EXPORTS
  817. // and SEGMENTS directives in the .DEF file.
  818. //
  819. // Read the comments section documenting the WEP function in the Windows
  820. // 3.1 SDK "Programmers Reference, Volume 2: Functions" before placing
  821. // any additional code in the WEP routine for a Windows 3.0 DLL.
  822. //---------------------------------------------------------------------------
  823. #pragma alloc_text(WEP_TEXT,WEP)
  824.  
  825. //---------------------------------------------------------------------------
  826. // Performs cleanup tasks when the DLL is unloaded.  WEP() is
  827. // called automatically by Windows when the DLL is unloaded (no
  828. // remaining tasks still have the DLL loaded).    It is strongly
  829. // recommended that a DLL have a WEP() function, even if it does
  830. // nothing but returns success (1), as in this example.
  831. //---------------------------------------------------------------------------
  832. int FAR PASCAL WEP
  833. (
  834.     int fSystemExit
  835. )
  836. {
  837.     // Avoid warnings on unused (but required) formal parameters
  838.     fSystemExit = fSystemExit;
  839.  
  840.     return 1;
  841. }
  842. #endif // C6
  843.  
  844. //---------------------------------------------------------------------------
  845.